package com.bwda.dsrs.filecenter.quartz;

import com.bwda.dsrs.base.util.DateUtil;
import com.bwda.dsrs.filecenter.domain.po.tsktask.TskTaskPo;
import com.bwda.dsrs.filecenter.domain.po.tsktaskhistory.TskTaskHistoryPo;
import com.bwda.dsrs.filecenter.domain.vo.tsktask.ScheduleJobVo;
import com.bwda.dsrs.filecenter.service.TskTaskHistoryService;
import com.bwda.dsrs.filecenter.service.TskTaskService;
import com.bwda.dsrs.systemservice.domain.Constants;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * Description: 任务基类，提供公共方法
 *
 * @author liuxiaoyong
 * @date 2019/11/23
 */
@Component
public abstract class AbstractBaseTask implements Job {

    private static Logger logger = LoggerFactory.getLogger(AbstractBaseTask.class);


    /**
     * Description: 执行具体任务的抽象方法，由子类实现
     *
     * @return boolean 执行结果
     * @throws TaskServiceException 异常信息
     * @exception TaskServiceException 异常信息
     */
    protected abstract boolean executeTask() throws TaskServiceException;



    /**
     * Description: 继承至Job类的执行方法，该方法执行公共功能，如设置任务执行状态和记录日志，具体任务由子类实现
     *
     * @param jobExecutionContext job信息
     * @return boolean
     */
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        ScheduleJobVo vo = getScheduleJobVo(jobExecutionContext);

        logger.info("{}.{} task is executed......", vo.getJobGroup(), vo.getJobName());

        //任务开始执行，设置任务状态为执行中
        setTaskStatusExecuting(vo);

        //任务执行开始时间
        Date beginTime = new Date();
        //执行结果初始化为成功
        long result = Constants.TaskResult.SUCCESS;

        try {
            //执行子类的具体任务
            boolean b = executeTask();

            logger.info("{}.{} task is executed successfully......", vo.getJobGroup(), vo.getJobName());
        } catch (Exception e) {
            logger.error("{}.{} task is executed failure......", vo.getJobGroup(), vo.getJobName());
            logger.error("error msg: {}", e);
            result = Constants.TaskResult.FAILURE;
        } finally {
            //任务执行完毕，设置任务状态为未执行
            setTaskStatusNotExecute(vo);

            //记录任务执行历史
            addTaskHistory(vo, beginTime, result);
        }
    }

    /**
     * Description: 记录任务执行历史
     *
     * @param vo        job信息
     * @param beginTime 执行开始时间
     * @param result    执行结果
     */
    private void addTaskHistory(ScheduleJobVo vo, Date beginTime, long result) {
        //任务执行结束时间
        Date endTime  = new Date();

        TskTaskHistoryService taskHistoryService = SpringUtil.getBean(TskTaskHistoryService.class);
        TskTaskHistoryPo po = new TskTaskHistoryPo();
        po.setTaskId(vo.getJobId());
        po.setTaskName(vo.getJobName());
        po.setTaskGroup(vo.getJobGroup());
        po.setExeClass(vo.getBeanClass());
        po.setBeginTime(beginTime);
        po.setEndTime(endTime);
        po.setResult(result);

        //计算开始时间和结束时间之间的时差,单位毫秒
        long duration = DateUtil.msBetween(beginTime, endTime);
        po.setExeDuration(duration);

        taskHistoryService.insert(po);
    }

    /**
     * Description: 设置任务状态为执行中
     *
     * @param vo job信息
     */
    private boolean setTaskStatusExecuting(ScheduleJobVo vo) {
        return updateTaskExeStatus(vo, Constants.TaskExeStatus.EXECUTING);
    }

    /**
     * Description: 设置任务状态为未执行
     *
     * @param vo job信息
     */
    private boolean setTaskStatusNotExecute(ScheduleJobVo vo) {
        return updateTaskExeStatus(vo, Constants.TaskExeStatus.NOT_EXECUTE);
    }

    /**
     * Description: 设置任务执行状态
     *
     * @param vo        job信息
     * @param exeStatus 执行状态
     * @return boolean
     */
    private boolean updateTaskExeStatus(ScheduleJobVo vo, Long exeStatus) {
        TskTaskService taskService = SpringUtil.getBean(TskTaskService.class);
        TskTaskPo po = new TskTaskPo();
        po.setTaskId(vo.getJobId());
        po.setExeStatus(exeStatus);

        int count = taskService.update(po);



        return count > 0;
    }

    /**
     * Description: 获取JOB对象     *
     *
     * @param jobExecutionContext job信息
     * @return ScheduleJobVo
     */
    private ScheduleJobVo getScheduleJobVo(JobExecutionContext jobExecutionContext) {
        ScheduleJobVo vo = (ScheduleJobVo) jobExecutionContext.getJobDetail().getJobDataMap().get("scheduleJob");
        return vo;
    }

}
